package eerbaar.v2.pattern.server.internal;

import java.util.UUID;

import eerbaar.client.ctr.OperatorConstants;
import eerbaar.server.statemachine.Machine;
import eerbaar.server.statemachine.State;
import eerbaar.shared.tree.INode;
import eerbaar.shared.tree.NodeFactory;

public class ProgramGenerator extends AbstractGenerator {

    private final Machine machine = new Machine();
    private final Machine machine2 = new Machine();

    public ProgramGenerator() {
        //
    }

    private boolean checkPattern(final String[] patterns, final String inPattern) {

        boolean found = false;
        for (String pattern : patterns) {

            if (pattern.equals(inPattern)) {

                found = true;
                break;
            }
        }

        return found;
    }

    private void checkProgram1() {

        final String[] patterns = { "[(a->b)*, (b->a)*]", "[(a->b)*, (b->a)]",
                "[(a->b), (b->a)]" };

        String testPattern = this.machine.simpleString();
        if (checkPattern(patterns, testPattern)) {

            State a = this.machine.simpleState("a");
            State b = this.machine.simpleState("b");
            assert (a != null);
            assert (b != null);

            String wordA = a.getWord();
            String wordB = b.getWord();
            String program = "( " + wordA + " " + wordB + " {seq} )";

            String word = UUID.randomUUID().toString();
            INode idea = NodeFactory.create(word, program);

            super.fireProgramFound(idea);
        }
    }

    private void checkProgram2() {

        final String[] patterns = { "[(cmd->cmd), (cmd->collision)]",
                "[(cmd->cmd)*, (cmd->collision)]", "[(cmd->collision)]" };

        String testPattern = this.machine2.string();
        if (checkPattern(patterns, testPattern)) {

            State last = this.machine.lastState();
            assert (last != null);

            String word = last.getWord();
            String program = "( " + word + " " + OperatorConstants.ATTRACT
                    + " )";

            String programName = UUID.randomUUID().toString();
            INode idea = NodeFactory.create(programName, program);

            super.fireProgramFound(idea);
        }
    }

    private void checkProgram3() {

        final String[] patterns = { "[(cmd->cmd), (cmd->collision2)]",
                "[(cmd->cmd)*, (cmd->collision2)]", "[(cmd->collision2)]" };

        String testPattern = this.machine2.string();
        if (checkPattern(patterns, testPattern)) {

            State last = this.machine.lastState();
            assert (last != null);

            String word = last.getWord();
            String program = "( " + word + " " + OperatorConstants.REPEL + " )";

            String programName = UUID.randomUUID().toString();
            INode idea = NodeFactory.create(programName, program);

            super.fireProgramFound(idea);
        }
    }

    private void checkProgram4() {

        final String[] patterns = { "[(cmd->cmd), (cmd->edge)]",
                "[(cmd->cmd)*, (cmd->edge)]", "[(cmd->edge)]" };

        String testPattern = this.machine2.string();
        if (checkPattern(patterns, testPattern)) {

            State last = this.machine.lastState();
            assert (last != null);

            String program = "( " + "bug" + " " + OperatorConstants.REPEL
                    + " )";

            String programName = UUID.randomUUID().toString();
            INode idea = NodeFactory.create(programName, program);

            super.fireProgramFound(idea);
        }
    }

    private void checkProgram5() {

        final String[] patterns = { "[(cmd->cmd), (cmd->edge)]",
                "[(cmd->cmd)*, (cmd->edge)]", "[(cmd->edge)]" };

        String testPattern = this.machine2.string();
        if (checkPattern(patterns, testPattern)) {

            State last = this.machine.lastState();
            assert (last != null);

            String program = "( " + "bug" + " " + OperatorConstants.REPEL
                    + " )";

            String programName = UUID.randomUUID().toString();
            INode idea = NodeFactory.create(programName, program);

            super.fireProgramFound(idea);
        }
    }

    private void checkProgram6() {

        final String[] patterns = { "[(cmd->cmd), (cmd->collision3)]",
                "[(cmd->cmd)*, (cmd->collision3)]", "[(cmd->collision3)]" };

        String testPattern = this.machine2.string();
        if (checkPattern(patterns, testPattern)) {

            State last = this.machine.lastState();
            assert (last != null);

            String word = last.getWord();
            String program = "( " + word + " " + OperatorConstants.ATTRACT
                    + " )";

            String programName = UUID.randomUUID().toString();
            INode idea = NodeFactory.create(programName, program);

            super.fireProgramFound(idea);
        }
    }

    private void checkPrograms() {

        checkProgram1();
        checkProgram2();
        checkProgram3();
        checkProgram4();
        checkProgram5();
        checkProgram6();
    }

    @Override
    public void eatEvent(String event) {

        eatEvent("undef", event);
    }

    @Override
    public void eatEvent(String eventClass, String event) {

        String clazz = "undef";
        if (eventClass != null) {
            clazz = eventClass;
        }

        State state = new State(event);
        this.machine.record(state);

        State state2 = new State(clazz);
        this.machine2.record(state2);

        checkPrograms();

        System.out.print(this.machine);
        System.out.println(this.machine2.string());
    }

}
